package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.BrandDTO;
import com.leyou.item.entity.Brand;
import com.leyou.item.entity.CategoryBrand;
import com.leyou.item.mapper.BrandMapper;
import com.leyou.item.service.BrandService;
import com.leyou.item.service.CategoryBrandService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.beans.Transient;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements BrandService {

    @Autowired
    private CategoryBrandService categoryBrandService;

    //品牌分页查询
    @Override
    public PageDTO<BrandDTO> pageQuery(Integer page, Integer rows, String key) {
        //分页条件定义
        IPage<Brand> iPage = new Page<>(page, rows);
        boolean isCondition = StringUtils.isNotBlank(key);
        //分页查询,不用获取，信息发生自动回填，相当于主键回显

        //select * tb_brand [where name like %key% or letter=key] limit 0,5
        //Quer'yWapper 查询条件的封装，并不是整个sql的条件，分页条件，和这个条件要融合
        //这里只是条件的定义，真的执行，会在内部二次封装
        page(iPage, new QueryWrapper<Brand>()
                .like(isCondition, "name", key)
                .or()
                .eq(isCondition, "letter", key)
        );
        //封装分页查询返回的结果
        return new PageDTO<>(iPage.getTotal(), iPage.getPages(), BrandDTO.convertEntityList(iPage.getRecords()));
    }

    //根据id查询对应的品牌对象
    @Override
    public BrandDTO queryBrandById(Long id) {
        return new BrandDTO(this.getById(id));
    }

    //根据分类id查询品牌集合
    @Override
    public List<BrandDTO> queryBrandByCategory(Long id) {

        //先查询中间表根据分类id，获取到分类品牌的中间对象的集合，取出品牌id集合，根据品牌id集合查询对应的品牌集合
        List<Long> brandIds = this.categoryBrandService
                .query()
                .eq("category_id", id)
                .list()
                .stream()
                .map(CategoryBrand::getBrandId)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(brandIds)) {
            throw new LyException(204, "当前分类对应的品牌不存在");
        }

        return listBrandByIds(brandIds);
    }

    //根据id集合查询对应的品牌集合
    @Override
    public List<BrandDTO> listBrandByIds(List<Long> ids) {
        List<Brand> brands = listByIds(ids);
        return BrandDTO.convertEntityList(brands);
    }

    @Override
    @Transactional
    public void addBrand(BrandDTO brandDTO) {
        //dto ==>entity
        Brand brand = brandDTO.toEntity(Brand.class);
        //保持品牌并回显品牌id
        this.save(brand);
        //从dto中获取分类的id集合，并结合品牌id，生成中间表对象
        saveCategoryAndBrand(brandDTO.getCategoryIds(), brand.getId());
    }

    private void saveCategoryAndBrand(List<Long> cids, Long bid) {
        List<CategoryBrand> categoryBrands = cids
                .stream()
                .map(cid -> CategoryBrand.of(cid, bid))
                .collect(Collectors.toList());

        this.categoryBrandService.saveBatch(categoryBrands);
    }

    @Override
    public void updateBrand(BrandDTO brandDTO) {
        Brand brand = brandDTO.toEntity(Brand.class);

        this.updateById(brand);

        //中间表，先删除逻辑关系重建逻辑
        //delete from tb_category_brand where brand_id = #{brandId}
        this.categoryBrandService.remove(new QueryWrapper<CategoryBrand>().eq("brand_id", brand.getId()));

        //重建品牌和分类的关系
        saveCategoryAndBrand(brandDTO.getCategoryIds(), brand.getId());

    }
}
